
#include <iostream>
#include <math.h>
#include <string.h>

#include "Matrix4.h"
#include "MatrixHelpers.h"

namespace Krengine
{
	/**
	 * returns the identity matrix
	 */
	const Matrix4 identityMatrix()
	{
		Matrix4 ident;

		ident.data[0]  = 1.0f;
		ident.data[5]  = 1.0f;
		ident.data[10] = 1.0f;
		ident.data[15] = 1.0f;

		return Matrix4(ident);
	}


	/**
	 * Generate a perspective view matrix using a field of view angle fov,
	 * window aspect ratio, near and far clipping planes
	 */
	const Matrix4 perspectiveMatrix( float fov, float aspect, float nearz, float farz )
	{
		/* reset matrix */
		Matrix4 projMatrix;

		/* create projection matrix */
		double piOver360 = (4.0 * atan(1.0)) / 360.0;
		float range = (float)tan(fov * piOver360) * nearz;
		projMatrix.data[0]  = (2 * nearz) / ((range * aspect) - (-range * aspect));
		projMatrix.data[5]  = (2 * nearz) / (2 * range);
		projMatrix.data[10] = -(farz + nearz) / (farz - nearz);
		projMatrix.data[11] = -1;
		projMatrix.data[14] = -(2 * farz * nearz) / (farz - nearz);

		return Matrix4(projMatrix);
	}


	/**
	 * Translation matrix for transforming along vector (x,y,z)^T
	 */
	const Matrix4 translateMatrix( float x, float y, float z )
	{
		Matrix4 tranMatrix = identityMatrix();

		tranMatrix.data[12] = x;
		tranMatrix.data[13] = y;
		tranMatrix.data[14] = z;

		return Matrix4(tranMatrix);
	}


	/**
	 * Rotation matrix for rotating about the x-axis of a moving frame
	 */
	const Matrix4 rotateLocalXMatrix( float angle )
	{
		std::vector<float> rotData(16, 0);

		rotData[0]  = 1.0f;
		rotData[5]  = rotData[10] = cos(angle);
		rotData[6]  = -sin(angle);
		rotData[9]  = -rotData[6];
		rotData[15] = 1.0f;

		return Matrix4(rotData);
	}

	/**
	 * Rotation matrix for rotating about the y-axis of a moving frame
	 */
	const Matrix4 rotateLocalYMatrix( float angle )
	{
		std::vector<float> rotData(16, 0);

		rotData[0]  = rotData[10] = cos(angle);
		rotData[5]  = 1.0f;
		rotData[2]  = sin(angle);
		rotData[8]  = -rotData[2];
		rotData[15] = 1.0f;

		return Matrix4(rotData);
	}

	/**
	 * Rotation matrix for rotating about the x-axis of a moving frame
	 */
	const Matrix4 rotateLocalZMatrix( float angle )
	{
		std::vector<float> rotData(16, 0);

		rotData[0]  = rotData[5] = cos(angle);
		rotData[1]  = -sin(angle);
		rotData[4]  = -rotData[1];
		rotData[10] = rotData[15] = 1.0f;

		return Matrix4(rotData);
	}
}
